<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>无缝滚动2</title>
    <link rel="stylesheet" href="./banner.css" />
    <script src="./animate.js"></script>
  </head>

  <body>
    <div class="banner">
      <!-- 轮播图 -->
      <ul class="imgBox clearFix">
        <!-- <li class="slider" style="background-color: yellow">E</li> -->
        <li class="slider" style="background-color: red">A</li>
        <li class="slider" style="background-color: orange">B</li>
        <li class="slider" style="background-color: green">C</li>
        <li class="slider" style="background-color: pink">D</li>
        <li class="slider" style="background-color: yellow">E</li>
        <!-- <li class="slider" style="background-color: red">A</li> -->
      </ul>

      <!-- 指示器存放处 -->
      <ol class="pointBox"></ol>

      <div class="leftRightTabs">
        <a class="prev">&lt;</a>
        <a class="next">&gt;</a>
      </div>
    </div>

    <script>
      var box, ul, sliders, ol, btns, btnPrev, btnNext, pointers;
      // 当前页码(0~6)  [5]12345[1]
      var currentIndex = 1;

      // 记录animate动画是否正在运行（运行期间对上下张按钮进行事件节流）
      var animIsRunning = false;

      // 记录是否正在拖拽（不曾down下鼠标则mousemove事件不会导致幻灯片跟随）
      var isDragging = false;

      // down下鼠标时的事件位置、轮播图位置（移动鼠标时计算扫过的偏移量，鼠标偏移多少，轮播图就跟着偏移多少）
      var downMouseX = 0,downUlLeft = 0;

      // 自动轮播定时器（全局仅此一例）
      // 如果有一堆定时器叠加则动画速度会变快
      var autoplayTimer = null;

      /* 找出元素 */
      function findElements() {
        // 外层容器
        box = document.querySelector(".banner");

        // 轮播图
        ul = document.querySelector(".imgBox");

        // 幻灯片页
        sliders = ul.querySelectorAll(".slider");

        // 指示器容器
        ol = document.querySelector(".pointBox");

        // 上一张 下一张
        btns = document.querySelector(".leftRightTabs");
        btnPrev = document.querySelector(".prev");
        btnNext = document.querySelector(".next");
      }

      /* 添加欺骗头尾 [5]12345[1]*/
      function initLoop() {
        ul.innerHTML =
          `<li class="slider" style="background-color: yellow">5</li>` +
          ul.innerHTML +
          `<li class="slider" style="background-color: red">1</li>`;
        ul.style.width = 600 * 7 + "px";
      }

      /* 添加指示器 */
      function initPointers() {
        // 每张幻灯片对应一个指示器小圆点
        sliders.forEach(function (slider, index) {
          var pointer = document.createElement("li");
          pointer.setAttribute("index", index + 1);
          ol.appendChild(pointer);
        });
        // 找出所有的指示器
        pointers = ol.querySelectorAll("li");
      }

      /* 跳转currentIndex */
      function animateToCurrentIndex() {
        // 不接受两个动画同时跑
        animIsRunning = true;
        console.log(currentIndex);
        animate(
          ul, //想染谁动
          { left: -600 * currentIndex + "px" }, //目标状态
          500, //耗时
          // 动画结束回调函数
          function () {
            // console.log("动画结束了，callback被回调了", currentIndex);

            /* 移形换影 6=>1 0=>5*/
            if (currentIndex === 6) {
              currentIndex = 1;
              // 瞬间移位
              ul.style.left = -600 * currentIndex + "px";
            }
            if (currentIndex === 0) {
              currentIndex = 5;
              // 瞬间移位
              ul.style.left = -600 * currentIndex + "px";
            }

            // 对应的指示器高亮
            updatePointers();

            animIsRunning = false;
          }
        );
      }

      /* 页码更新时 指示器也随之更新 */
      function updatePointers() {
        pointers.forEach(function (p) {
          p.classList.remove("active");
        });

        /* 更新指示器思路一 */
        // currentIndex = 【0】 1 2 3 4 5 【6】
        // pointersIndex =      0 1 2 3 4
        // pointers[currentIndex - 1].classList.add("active");

        /* 更新指示器思路二 */
        // 找出index属性为currentIndex的指示器，令其高亮
        // 将指示器伪数组转为真数组（以便使用批处理函数find）
        var pointerArr = Array.from(pointers);
        // find的作用相当于filter后取第0个符合条件的元素
        var p = pointerArr.find(function (pointerLi) {
          // 哪个指示器li暗藏的index属性值等当前页码
          return pointerLi.getAttribute("index") == currentIndex;
        });

        if (p) {
          p.classList.add("active");
        }
      }

      // 上一张
      function prev() {
        // 如果当前动画正在运行 直接节流掉
        if (animIsRunning) return;

        currentIndex--;
        animateToCurrentIndex();
      }

      // 下一张
      function next() {
        // 如果当前动画正在运行 直接节流掉
        if (animIsRunning) return;

        currentIndex++;
        animateToCurrentIndex();
      }

      /* 自动轮播 */
      function startAutoPlay() {
        if (!autoplayTimer) {
          autoplayTimer = setInterval(function () {
            next();
          }, 2000);
        }
      }

      /* 当鼠标覆盖ul时停止轮播 */
      function stopAutoPlay() {
        if (autoplayTimer) {
          clearInterval(autoplayTimer);

          // 标记轮播已停止
          autoplayTimer = null;
        }
      }

      function initListeners() {
        btnPrev.onclick = function (e) {
          // 让Ul的left样式-600像素
          // ul.style.left = parseFloat(getComputedStyle(ul).left) + 600 + "px";
          prev();
        };

        btnNext.onclick = function (e) {
          // 让Ul的left样式-600像素
          // ul.style.left = parseFloat(getComputedStyle(ul).left) - 600  +"px"
          next();
        };

        // 点击指示器
        ol.onclick = function (e) {
          if (e.target.nodeName === "LI") {
            var index = e.target.getAttribute("index");
            console.log(index);

            // 滑动到对应的目标页
            currentIndex = index;
            animateToCurrentIndex();
          }
        };

        ul.onmouseenter = function (e) {
          stopAutoPlay();
        };
        btns.onmouseenter = function (e) {
          stopAutoPlay();
        };

        /* 当鼠标离开ul时开始轮播 */
        box.onmouseleave = function (e) {
          startAutoPlay();
        };

        /* 在轮播图身上按下鼠标 */
        ul.onmousedown = function (e) {
          // 标记拖拽开始
          isDragging = true;
          console.log("e.pageX/boxMarginLeft", e.pageX, boxMarginLeft);

          // 记录鼠标down下位置与ul的left
          // 移动鼠标时计算扫过的偏移量，鼠标偏移多少，轮播图就跟着偏移多少
          downMouseX = e.pageX;
          downUlLeft = parseFloat(window.getComputedStyle(ul).left);
        };

        // 在box内部mousemove ul跟随
        ul.onmousemove = function (e) {
          // 如果曾经在轮播图身上按下过鼠标 则轮播图跟随 （否则啥也不干）
          if (isDragging) {
            // console.log("ul跟着鼠标走");

            // 鼠标距离按下时偏移多少，ul的left跟着偏移多少
            ul.style.left = downUlLeft + (e.pageX - downMouseX) + "px";
          }
        };

        // 在任意位置抬起鼠标停止拖拽
        document.onmouseup = function (e) {
          // 如果不曾按下 则没有撒手逻辑
          if (isDragging === false) return;

          // 标记拖拽停止
          isDragging = false;

          /* 撒手时 三个选项：动画到上一张 动画到下一张 动画到本张的初识位置 */

          // 具体走哪种选择取决于撒手时距离按下时走过的偏移量
          // 计算出这个该死的偏移量
          var offsetX = e.pageX - downMouseX;

          // 向右大力扫=动画到上一张
          if (offsetX >= 200) {
            prev();
          }

          // 向左大力扫=动画到下一张
          else if (offsetX <= -200) {
            next();
          }

          // 动画到本张的初识位置
          else {
            // 页码未变 -1250px=>-1200px
            animateToCurrentIndex();
          }
        };
      }

      /* 核心业务逻辑 */
      function main() {
        findElements();
        initLoop();
        initPointers();
        updatePointers();
        startAutoPlay();
        initListeners();
      }
      main();
      
    </script>
  </body>
</html>
